package com.jiangyifen.robot.websocket;

import java.io.IOException;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jiangyifen.robot.websocket.internal.WebsocketCache;

@ServerEndpoint(value = "/websocket/{clientId}")
public class WebSocketEndpoint {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	public WebSocketEndpoint() {
		logger.debug("new WebSocketEndpoint()");
	}

	@OnOpen
	public void onOpen(@PathParam("clientId") String clientId, Session session) {
		logger.debug("Websocket OnOpen! clientId={}, session={}", clientId, session.getId());
		// 1)先清理该clientId的已连接上的session
		sendLogout(clientId);
		// 2)把当前新连接上的session放入map
		WebsocketCache.connections.put(clientId, session);
	}

	@OnClose
	public void onClose(@PathParam("clientId") String clientId, Session session) {
		logger.debug("Websocket OnClose! clientId={}, session={}", clientId, session.getId());
	}

	@OnMessage
	public void onMessage(@PathParam("clientId") String clientId, Session session, String message) {
		// 目前我们主要用websocket向浏览器推送消息，浏览器向服务器发送的主要是心跳，所以这里什么都不用做
		logger.debug(message);
	}

	@OnError
	public void onError(Throwable t, Session session) throws Throwable {
		Thread.sleep(500);
		logger.error("Websocket OnError: " + t.toString());
	}

	// 向浏览器发送登出命令，浏览器收到后，自己执行登出，并且断开websocket连接
	private void sendLogout(String clientId) {
		Session session = WebsocketCache.connections.get(clientId);
		if (session != null) {
			// 在这里把session从map里移除，而不是在onclose的时候。
			// 因为logout命令发出去后，在onopen里，新的session会先放入到map，浏览器的连接后断（网络传输慢，本地调用快）。
			// 而这个后断的连接会触发onclose。如果onclose执行map.remove，会把新的session移掉
			WebsocketCache.connections.remove(clientId);
			try {
				synchronized (session) {
					if (session.isOpen()) {
						session.getBasicRemote().sendText("{\"eventName\":\"logout\"}");
						logger.debug("向old websocket session " + session.getId() + " 发送logout命令！");
					}
				}
			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
		}
	}

}
